/*
 * @Author: fuhongliang-TSJ hongliang.fu@4d-bios.com
 * @Date: 2025-10-10 10:08:41
 * @LastEditTime: 2025-10-10 16:24:56
 * @LastEditors: fuhongliang-TSJ hongliang.fu@4d-bios.com
 * @Description: 
 * @FilePath: \lc_-esp32_-s3\main\lc\handheld\music_app.c
 * 立创实战派ESP32-S3开发板
 * Copyright (c) 2025 by 4D Bios, All Rights Reserved. 
 */

#include "handheld.h"
#include "bsp_lvgl.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "string.h"
#include <dirent.h>
#include "audio.h"
#include "audio_player.h"
#include "file_iterator.h"
#include "sd_card.h"
#include "bsp_spiffs.h"
#include "bsp_lvgl.h"
#include "pca9557.h"
#include "mp3_player.h"
#include "esp_log.h"
#include "esp_check.h"

static const char *TAG = "music_app";

extern lv_obj_t *icon_in_obj; // 应用界面
extern int icon_flag;

// 声明使用的字体
LV_FONT_DECLARE(font_alipuhui20);

static audio_player_config_t player_config = {0};
static uint8_t g_sys_volume = VOLUME_DEFAULT;
static file_iterator_instance_t *file_iterator = NULL;
static const char *mp3_file_path = NULL;
static button_style_t g_btn_styles;

static lv_obj_t *label_title; // 标题栏文字
static lv_obj_t *music_list;

int file_storage_type = 0;

/**
 * @description: mp3文件路径寻找
 * @return {*}
 */
static void mp3_file_find(void)
{
   esp_err_t ret;

   ret = sd_init();

   if(ret == ESP_OK)
   {
      mp3_file_path = MOUNT_POINT"/mp3";
      file_storage_type = 1;
   }
   else if (ret != ESP_OK)
   {
      bsp_spiffs_mount();
      mp3_file_path = SPIFFS_BASE;
      file_storage_type = 0;
      ESP_LOGI(TAG, "SD card not found, please insert an SD card.");
      ESP_LOGI(TAG, "Now init spiffs.");
   }   
}

// 返回当前声音大小
static uint8_t get_sys_volume()
{
    return g_sys_volume;
}

// 播放指定序号的音乐
static void play_index(int index)
{
    ESP_LOGI(TAG, "play_index(%d)", index);

    char filename[128];
    int retval = file_iterator_get_full_path_from_index(file_iterator, index, filename, sizeof(filename));
    if (retval == 0) {
        ESP_LOGE(TAG, "unable to retrieve filename");
        return;
    }

    FILE *fp = fopen(filename, "rb");
    if (fp) {
        ESP_LOGI(TAG, "Playing '%s'", filename);
        audio_player_play(fp);
    } else {
        ESP_LOGE(TAG, "unable to open index %d, filename '%s'", index, filename);
    }
}

// 设置声音处理函数
static esp_err_t _audio_player_mute_fn(AUDIO_PLAYER_MUTE_SETTING setting)
{
   esp_err_t ret = ESP_OK;

   // 获取当前音量
   uint8_t volume = get_sys_volume();
   // 判断是否需要静音
   bsp_codec_mute_set(setting == AUDIO_PLAYER_MUTE ? true : false);
   // 如果不是静音 设置音量
   if (setting == AUDIO_PLAYER_UNMUTE) {
      bsp_codec_volume_set(volume, NULL);
   }
   ret = ESP_OK;

   return ret;
}

// 播放音乐函数 播放音乐的时候 会不断进入
static esp_err_t _audio_player_write_fn(void *audio_buffer, size_t len, size_t *bytes_written, uint32_t timeout_ms)
{
   esp_err_t ret = ESP_OK;

   ret = bsp_i2s_write(audio_buffer, len, bytes_written, timeout_ms);

   return ret;
}

// 设置采样率 播放的时候进入一次
static esp_err_t _audio_player_std_clock(uint32_t rate, uint32_t bits_cfg, i2s_slot_mode_t ch)
{
   esp_err_t ret = ESP_OK;

   ret = bsp_codec_set_fs(rate, bits_cfg, ch);

   return ret;
}

// 回调函数 播放器每次动作都会进入
static void _audio_player_callback(audio_player_cb_ctx_t *ctx)
{
   ESP_LOGI(TAG, "ctx->audio_event = %d", ctx->audio_event);
   switch (ctx->audio_event) {
   case AUDIO_PLAYER_CALLBACK_EVENT_IDLE: {  // 播放完一首歌 进入这个case
      ESP_LOGI(TAG, "AUDIO_PLAYER_REQUEST_IDLE");
      // 指向下一首歌
      file_iterator_next(file_iterator);
      int index = file_iterator_get_index(file_iterator);
      ESP_LOGI(TAG, "playing index '%d'", index);
      play_index(index);
      // 修改当前播放的音乐名称
      lvgl_port_lock(0);
      lv_dropdown_set_selected(music_list, index);
      lvgl_port_unlock();
      break;
   }
   case AUDIO_PLAYER_CALLBACK_EVENT_PLAYING:  // 播放音乐
      ESP_LOGI(TAG, "AUDIO_PLAYER_REQUEST_PLAY");
      pa_en(1);  // 打开音频功放
      break;
   case AUDIO_PLAYER_CALLBACK_EVENT_PAUSE:   // 暂停音乐
      ESP_LOGI(TAG, "AUDIO_PLAYER_REQUEST_PAUSE");
      pa_en(0);  // 关闭音频功放
      break;
   default:
      break;
   }
}

static button_style_t *ui_button_styles(void)
{
    return &g_btn_styles;
}

// 按钮样式初始化
static void ui_button_style_init(void)
{
    /*Init the style for the default state*/
    lv_style_init(&g_btn_styles.style_focus_no_outline);
    lv_style_set_outline_width(&g_btn_styles.style_focus_no_outline, 0);

    lv_style_init(&g_btn_styles.style_bg);
    lv_style_set_bg_opa(&g_btn_styles.style_bg, LV_OPA_100);
    lv_style_set_bg_color(&g_btn_styles.style_bg, lv_color_white());
    lv_style_set_shadow_width(&g_btn_styles.style_bg, 0);
}

// 播放暂停按钮 事件处理函数
static void btn_play_pause_cb(lv_event_t *event)
{
   lv_obj_t *btn = lv_event_get_target(event);
   lv_obj_t *label = (lv_obj_t *)btn->user_data;

   audio_player_state_t state = audio_player_get_state();
   printf("state=%d\n", state);

   if (state == AUDIO_PLAYER_STATE_IDLE)
   {
      lvgl_port_lock(0);
      lv_label_set_text_static(label, LV_SYMBOL_PAUSE);
      lvgl_port_unlock();

      int index = file_iterator_get_index(file_iterator);
      ESP_LOGI(TAG, "playing index '%d'", index);
      play_index(index);
   }
   else if (state == AUDIO_PLAYER_STATE_PAUSE)
   {
      lvgl_port_lock(0);
      lv_label_set_text_static(label, LV_SYMBOL_PAUSE);
      lvgl_port_unlock();
      audio_player_resume();
   }
   else if (state == AUDIO_PLAYER_STATE_PLAYING)
   {
      lvgl_port_lock(0);
      lv_label_set_text_static(label, LV_SYMBOL_PLAY);
      lvgl_port_unlock();
      audio_player_pause();
   }
}

// 上一首 下一首 按键事件处理函数
static void btn_prev_next_cb(lv_event_t *event)
{
   lv_obj_t *btn = lv_event_get_target(event);

   bool is_next = (bool) event->user_data;

   if (is_next) {
      ESP_LOGI(TAG, "btn next");
      file_iterator_next(file_iterator);
   } else {
      ESP_LOGI(TAG, "btn prev");
      file_iterator_prev(file_iterator);
   }

   // 修改当前的音乐名称
   int index = file_iterator_get_index(file_iterator);
   lvgl_port_lock(1);
   lv_dropdown_set_selected(music_list, index);
   lvgl_port_unlock();
   // 执行音乐事件
   audio_player_state_t state = audio_player_get_state();
   if (state == AUDIO_PLAYER_STATE_IDLE) {
      // nothing to do, changing songs while not playing
      // doesn't start or stop playback
      ESP_LOGI(TAG, "idle, nothing to do");
   } else if (state == AUDIO_PLAYER_STATE_PAUSE) {  // 如果当前正在暂停歌曲
      ESP_LOGI(TAG, "playing index '%d'", index);
      play_index(index);
      audio_player_resume();
   } else if (state == AUDIO_PLAYER_STATE_PLAYING) {  // 如果当前正在播放歌曲
      ESP_LOGI(TAG, "playing index '%d'", index);
      play_index(index);
   }
}

// 音量调节滑动条 事件处理函数
static void slider_volume_cb(lv_event_t *event)
{
   lv_obj_t *slider = lv_event_get_target(event);
   int volume= lv_slider_get_value(slider);  // 获取slider的值
   bsp_codec_volume_set(volume, NULL);  // 设置声音大小
   g_sys_volume = volume;  // 把声音赋值给g_sys_volume保存
   ESP_LOGI(TAG, "volue '%d'", volume);
}

// 音乐列表 点击事件处理函数
static void music_list_cb(lv_event_t *event)
{
   int16_t index = lv_dropdown_get_selected(music_list);
   ESP_LOGI(TAG, "switching index to '%d'", index);

   file_iterator_set_index(file_iterator, index);

   audio_player_state_t state = audio_player_get_state();
   printf("state=%d\n", state);
   if (state == AUDIO_PLAYER_STATE_PAUSE)
   {
      play_index(index);
      audio_player_pause();
   }
   else if (state == AUDIO_PLAYER_STATE_PLAYING)
   {
      play_index(index);
   }

}

// 音乐名称加入列表
static void build_file_list(lv_obj_t *music_list)
{
    lvgl_port_lock(0);
    lv_dropdown_clear_options(music_list);
    lvgl_port_unlock();

    for(size_t i = 0; i<file_iterator->count; i++)
    {
        const char *file_name = file_iterator_get_name_from_index(file_iterator, i);
        if (NULL != file_name) {
            lvgl_port_lock(0);
            lv_dropdown_add_option(music_list, file_name, i); // 添加音乐名称到列表中
            lvgl_port_unlock();
        }
    }
    lvgl_port_lock(0);
    lv_dropdown_set_selected(music_list, 0); // 选择列表中的第一个
    lvgl_port_unlock();
}

// 播放器界面初始化
static void music_app_ui(void)
{
   lvgl_port_lock(0);

   ui_button_style_init(); // 初始化按键风格

   /* 创建播放暂停控制按键 */
   lv_obj_t *btn_play_pause = lv_btn_create(icon_in_obj);
   lv_obj_align(btn_play_pause, LV_ALIGN_CENTER, 0, 40);
   lv_obj_set_size(btn_play_pause, 50, 50);
   lv_obj_set_style_radius(btn_play_pause, 25 , LV_STATE_DEFAULT);
   lv_obj_add_flag(btn_play_pause, LV_OBJ_FLAG_CHECKABLE);  // 这行代码让按钮能保持按下状态

   lv_obj_add_style(btn_play_pause, &ui_button_styles()->style_focus_no_outline, LV_STATE_FOCUSED);
   
   lv_obj_t *label_play_pause = lv_label_create(btn_play_pause);
   lv_label_set_text_static(label_play_pause, LV_SYMBOL_PLAY);
   lv_obj_center(label_play_pause);

   lv_obj_set_user_data(btn_play_pause, (void *)label_play_pause);
   lv_obj_add_event_cb(btn_play_pause, btn_play_pause_cb, LV_EVENT_VALUE_CHANGED, NULL);

   /* 创建上一首控制按键 */
   lv_obj_t *btn_play_prev = lv_btn_create(icon_in_obj);
   lv_obj_set_size(btn_play_prev, 50, 50);
   lv_obj_set_style_radius(btn_play_prev, 25 , LV_STATE_DEFAULT);
   lv_obj_align_to(btn_play_prev, btn_play_pause, LV_ALIGN_OUT_LEFT_MID, -40, 0);
   //lv_obj_clear_flag(btn_play_prev, LV_OBJ_FLAG_CHECKABLE);
   
   lv_obj_add_style(btn_play_prev, &ui_button_styles()->style_focus_no_outline, LV_STATE_FOCUSED);
   lv_obj_add_style(btn_play_prev, &ui_button_styles()->style_bg, LV_STATE_FOCUSED);
   lv_obj_add_style(btn_play_prev, &ui_button_styles()->style_bg, LV_STATE_DEFAULT);

   lv_obj_t *label_play_prev = lv_label_create(btn_play_prev);
   lv_label_set_text_static(label_play_prev, LV_SYMBOL_PREV);
   lv_obj_set_style_text_font(label_play_prev, &lv_font_montserrat_24, LV_STATE_DEFAULT);
   lv_obj_set_style_text_color(label_play_prev, lv_color_black(), LV_STATE_DEFAULT);
   lv_obj_center(label_play_prev);

   lv_obj_set_user_data(btn_play_prev, (void *)label_play_prev);
   lv_obj_add_event_cb(btn_play_prev, btn_prev_next_cb, LV_EVENT_CLICKED, (void *) false);

   /* 创建下一首控制按键 */
   lv_obj_t *btn_play_next = lv_btn_create(icon_in_obj);
   lv_obj_set_size(btn_play_next, 50, 50);
   lv_obj_set_style_radius(btn_play_next, 25 , LV_STATE_DEFAULT);
   lv_obj_align_to(btn_play_next, btn_play_pause, LV_ALIGN_OUT_RIGHT_MID, 40, 0);
   //lv_obj_clear_flag(btn_play_next, LV_OBJ_FLAG_CHECKABLE);
   
   lv_obj_add_style(btn_play_next, &ui_button_styles()->style_focus_no_outline, LV_STATE_FOCUSED);
   lv_obj_add_style(btn_play_next, &ui_button_styles()->style_bg, LV_STATE_FOCUSED);
   lv_obj_add_style(btn_play_next, &ui_button_styles()->style_bg, LV_STATE_DEFAULT);

   lv_obj_t *label_play_next = lv_label_create(btn_play_next);
   lv_label_set_text_static(label_play_next, LV_SYMBOL_NEXT);
   lv_obj_set_style_text_font(label_play_next, &lv_font_montserrat_24, LV_STATE_DEFAULT);
   lv_obj_set_style_text_color(label_play_next, lv_color_black(), LV_STATE_DEFAULT);
   lv_obj_center(label_play_next);

   lv_obj_set_user_data(btn_play_next, (void *)label_play_next);
   lv_obj_add_event_cb(btn_play_next, btn_prev_next_cb, LV_EVENT_CLICKED, (void *) true);

   /* 创建声音调节滑动条 */
   lv_obj_t *slider_volume = lv_slider_create(icon_in_obj);
   lv_slider_set_range(slider_volume, 0, 100);
   lv_slider_set_value(slider_volume, g_sys_volume, LV_ANIM_ON);
   lv_obj_set_size(slider_volume, 200, 6);
   lv_obj_align(slider_volume, LV_ALIGN_BOTTOM_MID, 0, -20);
   lv_obj_add_event_cb(slider_volume, slider_volume_cb, LV_EVENT_VALUE_CHANGED, NULL);

   lv_obj_t *label_vol_min = lv_label_create(icon_in_obj);
   lv_label_set_text_static(label_vol_min, LV_SYMBOL_VOLUME_MID);
   lv_obj_set_style_text_font(label_vol_min, &lv_font_montserrat_20, LV_STATE_DEFAULT);
   lv_obj_align_to(label_vol_min, slider_volume, LV_ALIGN_OUT_LEFT_MID, -10, 0);

   lv_obj_t *label_vol_max = lv_label_create(icon_in_obj);
   lv_label_set_text_static(label_vol_max, LV_SYMBOL_VOLUME_MAX);
   lv_obj_set_style_text_font(label_vol_max, &lv_font_montserrat_20, LV_STATE_DEFAULT);
   lv_obj_align_to(label_vol_max, slider_volume, LV_ALIGN_OUT_RIGHT_MID, 10, 0);

   /* 创建音乐标题 */
   music_list = lv_dropdown_create(icon_in_obj);
   lv_dropdown_clear_options(music_list);
   lv_dropdown_set_options_static(music_list, "扫描中...");
   lv_obj_set_style_text_font(music_list, &font_alipuhui20, LV_PART_MAIN);
   lv_obj_set_style_text_font(music_list, &lv_font_montserrat_20, LV_PART_INDICATOR); // 因为阿里普惠没有该符号的字体，设字体为LVGL自带的

   lv_obj_t *dropdown_list = lv_dropdown_get_list(music_list); // 获取music_list中的下拉列表
   lv_obj_set_style_text_font(dropdown_list, &font_alipuhui20, LV_PART_MAIN);

   lv_obj_set_width(music_list, 200);
   lv_obj_align(music_list, LV_ALIGN_TOP_MID, 0, 60);
   lv_obj_add_event_cb(music_list, music_list_cb, LV_EVENT_VALUE_CHANGED, NULL);

   build_file_list(music_list);

   lvgl_port_unlock();
}

/**
 * @description: mp3播放器初始化
 * @return {*}
 */
static void music_player_init(void)
{
    mp3_file_find();

    ESP_LOGI(TAG, "mp3_file_path %s", mp3_file_path);
    // 获取文件信息
    file_iterator = file_iterator_new(mp3_file_path);
    assert(file_iterator != NULL);

    // 初始化音频播放
    /* Initialize audio player, the default configuration is set to play through the USB headset. */
    player_config.mute_fn = _audio_player_mute_fn;
    player_config.write_fn = _audio_player_write_fn;
    player_config.clk_set_fn = _audio_player_std_clock;
    player_config.priority = 6;
    player_config.coreID = 1;

    ESP_ERROR_CHECK(audio_player_new(player_config));
    ESP_ERROR_CHECK(audio_player_callback_register(_audio_player_callback, NULL));
}

/**
 * @description: 返回主界面按钮事件处理函数
 * @param {lv_event_t} *e
 * @return {*}
 */
static void btn_back_cb(lv_event_t *e)
{
    lv_obj_del(icon_in_obj); //删除画布
    audio_player_delete();

    if (file_storage_type == 1)
    {
        sd_unmount();
    }
    else
    {
        bsp_spiffs_unmount();
    }

    icon_flag = 0;
}

/**
 * @description: 音乐播放器应用
 * @return {*}
 */
void music_app(void)
{
    // 初始化mp3播放器
    music_player_init();

    static lv_style_t style;
    lv_style_init(&style);
    lv_style_set_radius(&style, 10);
    lv_style_set_opa(&style, LV_OPA_COVER);
    lv_style_set_bg_color(&style, lv_color_hex(0xFFFFFF));
    lv_style_set_border_width(&style, 0);
    lv_style_set_pad_all(&style, 0);
    lv_style_set_width(&style, 320);
    lv_style_set_height(&style, 240);
    
    // 创建一个界面
    icon_in_obj = lv_obj_create(lv_scr_act());
    lv_obj_add_style(icon_in_obj, &style, 0);

    // 创建标题背景
    lv_obj_t *obj_title = lv_obj_create(icon_in_obj);
    lv_obj_set_size(obj_title, 320, 40);
    lv_obj_set_align(obj_title, LV_ALIGN_TOP_MID);
    lv_obj_set_style_pad_all(obj_title, 0, 0);  // 设置间隙
    lv_obj_set_style_bg_color(obj_title, lv_color_hex(0xf87c30), 0);

    label_title = lv_label_create(obj_title);
    lv_label_set_text(label_title, "音乐播放器");
    lv_obj_set_style_text_font(label_title, &font_alipuhui20, 0);
    lv_obj_set_style_text_color(label_title, lv_color_hex(0xffffff), 0);
    lv_obj_set_align(label_title, LV_ALIGN_CENTER);

    // 返回按钮
    lv_obj_t *btn_back = lv_btn_create(obj_title);
    lv_obj_align(btn_back, LV_ALIGN_LEFT_MID, 0, 0);
    lv_obj_set_size(btn_back, 60, 30);
    lv_obj_set_style_border_width(btn_back, 0, 0); // 设置边框宽度
    lv_obj_set_style_pad_all(btn_back, 0, 0);  // 设置间隙
    lv_obj_set_style_bg_opa(btn_back, LV_OPA_0, 0);
    lv_obj_set_style_shadow_opa(btn_back, LV_OPA_TRANSP, LV_PART_MAIN); // 阴影透明
    lv_obj_add_event_cb(btn_back, btn_back_cb, LV_EVENT_CLICKED, NULL);

    lv_obj_t *label_back = lv_label_create(btn_back);
    lv_label_set_text(label_back, LV_SYMBOL_LEFT);
    lv_obj_set_style_text_font(label_back, &lv_font_montserrat_20, 0);
    lv_obj_align(label_back, LV_ALIGN_CENTER, -10, 0);

    icon_flag = 2;

    music_app_ui(); // 音乐播放器界面
}